#ifndef INC_CONFIG_H_
#define INC_CONFIG_H_

#include <string>
#include <map>
#include <Poco/Mutex.h>
#include <Poco/Net/SocketAddress.h>

#define DEFAULT_UNICAST_PORT_MIN 4000
#define DEFAULT_UNICAST_PORT_MAX 5000
#define DEFAULT_RING_NAME "ring5001"
#define DEFAULT_MULTICAST_GROUP "239.0.0.1"
#define DEFAULT_NAMESERVER_GROUP "239.0.0.2:4000"
#define DEFAULT_NAMESERVER_DELAY 25000
#define DEFAULT_CHUNKSIZE 32768				// chunk size in bytes
#define DEFAULT_MAXARCHIVESIZE 2137593113		// Maximum size is a little less then 2 Gb ( in bytes )
/*********************************************************/
class Config
{
private:
	// Members
	static Config& 				pInstance;	// Only available instance of config
	static Poco::Mutex*			mutex;		// Mutual exclusion object for multithreading security

	// Configuration Parameters
	std::string				pNetworkMulticastGroup;		// Multicasting group used
	std::string 				pNetworkInterface;		// Networkinterface used
	std::string				pUnicastTrafficEvent;		// The unicast traffic reception event
	std::string				pMulticastTrafficEvent;		// The multicast traffic reception event
	std::string				pActivateProcessingEvent;	// The Activate processing event
	std::string				pInterfaceInputEvent;		// User generated input event
	std::string				pQuitEvent;			// Quit event string
	std::string				pRepository;			// File repository to use
	std::string				pDumpLog;			// Do we need to write a dump log at the end of execution?
	std::string				pNameServerGroup;		// Multicast group used to detect the nameserver
	std::string				pRingName;			// The name of the ring we want to join or joined
	unsigned int				pRingPort;			// The port over which we will communicate with the rest of the ring
	unsigned int				pNameServerDelay;		// The maximum time we will wait for the nameserver to respond
	unsigned int				pNetworkUnicastPortMax;		// Unicast port range maximum
	unsigned int				pNetworkUnicastPortMin;		// Unicast port range min
	unsigned long				pMaxArchiveSize;		// Maximum repository archive size
	unsigned long				pChunkSize;			// Repository chunk size
	float					pThreadPoolThreshold;		// Threadpool threshold
	int					pThreadPoolMin;			// Minimum threads available in the threadpool
	bool					pMultithreadedJobExecution;	// Multithreaded Job Execution
	bool					pUIEcho;			// Does the server echo interface commands?

	// Methods
	void writeDefaultConfig();
	bool parse();

	// Copy Construction/Assignment operator
	Config();						// Constructor
	Config( const Config& );				// Copy Constructor
	Config& operator=(const Config&);			// Assignment operator

protected:
public:
	// Methods for middleware configuration
	unsigned long getMaxArchiveSize() const;
	unsigned long getChunkSize() const;
	unsigned int getNetworkUnicastPortRangeMin() const;
	unsigned int getNetworkUnicastPortRangeMax() const;
	unsigned int getNameServerDelay() const;
	unsigned int getRingPort() const;
	std::string getNetworkMulticastGroup() const;
	std::string getRingName() const;
	std::string getNetworkInterface() const;
	std::string getQuitEvent() const;
	std::string getFileRepository() const;
	std::string getWriteDumpLog() const;
	std::string getNameServerGroup() const;
	float getThreadPoolThreshold() const;
	bool getMultithreadedJobExecution() const;
	bool getUIEcho() const;
	int getThreadPoolMin() const;
	
	void setQuitEvent(const std::string&);
	void setUIEcho(const bool);
	void setWriteDumpLog(const std::string&);
	void setNetworkMulticastGroup(const std::string&);
	void setNetworkInterface(const std::string&);
	void setNetworkUnicastPortRangeMin(const unsigned int&);
	void setNetworkUnicastPortRangeMax(const unsigned int&);
	void setMaxArchiveSize(const unsigned long&);
	void setChunkSize(const unsigned long&);
	void setMultithreadedJobExecution(const bool);
	void setThreadPoolThreshold(const float);
	void setThreadPoolMin(const unsigned int);
	void setFileRepository(const std::string&);
	void setNameServerGroup(const std::string&);
	void setRingName(const std::string&);
	void setNameServerDelay(const unsigned int&);
	void setRingPort(const unsigned int&);

	// Methods Event settings
	std::string getUnicastTrafficEvent() const;
	std::string getMulticastTrafficEvent() const;
	std::string getActivateProcessingEvent() const;
	std::string getInterfaceInputEvent() const;
	void setUnicastTrafficEvent(const std::string&);
	void setMulticastTrafficEvent(const std::string&);
	void setActivateProcessingEvent(const std::string&);
	void setInterfaceInputEvent(const std::string&);

	// Methods to reinitialize ( reparsing the config.ini file )
	void reparse();

	// Construction & Destruction
	static Config& Instance();				// Instance retrieval method
	virtual ~Config();					// Destructor
};
/*********************************************************/
#endif // INC_CONFIG_H_
